package com.eksframework.commons.core.converter;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Objects;

/**
 * StringConverter
 *
 * @author: chenfenghai
 * @version: 1.0
 * @date: 2020-04-24 14:22
 * @blame Team
 */
public class StringConverter<T> extends AbstractObjectConverter<T> {

    /** String对象 */
    private String stringObject;

    /**
     * Constructs an instance with the value present.
     *
     * @param object convert value
     */
    protected StringConverter(T object) {
        super(object);
    }

    /**
     * * 创建实例
     *
     * @param value 输入参数
     * @return not null
     */
    public static <T> StringConverter of(T value) {
        return new StringConverter<>(value);
    }

    //-----------------------------------------------------------------------------------------------------------------

    /**
     * <p>Convert a <code>Object</code> to a <code>String</code>
     *
     * @param value {@code Object} to convert to a {@code String}.
     * @return String
     * @throws NullPointerException – if the value is null.
     */
    private String convert(final T value) {
        Objects.requireNonNull(value);
        if (stringObject != null) {
            return stringObject;
        } else if (String.class.equals(value.getClass())) {
            this.stringObject = (String) value;
        } else if (value instanceof CharSequence) {
            this.stringObject = ((CharSequence) value).toString();
        } else {
            this.stringObject = value.toString();
        }
        return stringObject;
    }

    /**
     * <p>Convert a <code>Object</code> to a <code>String</code>
     * 
     * @return String
     * @see #toStringNull()
     */
    @Nullable
    @Override
    public String toString(){
        return toStringNull();
    }

    /**
     * <p>Convert a <code>Object</code> to a <code>String</code>, returning a
     * default value if the conversion fails.</p>
     *
     * @param defaultValue the default value
     * @return String
     * @see #convert(Object)
     */
    @Nullable
    public String toStringDefault(@Nullable final String defaultValue){
        return super.object == null ? defaultValue : convert(super.object);
    }

    /**
     * <p>Convert a <code>Object</code> to a <code>String</code>
     *
     * @return String
     * @see #toStringDefault(String)
     */
    @Nullable
    public String toStringNull(){
        return toStringDefault(null);
    }

    /**
     * <p>Convert a <code>Object</code> to a <code>String</code>
     *
     * @return String
     * @see #toStringDefault(String)
     */
    @Nonnull
    public String toStringEmpty(){
        return Objects.requireNonNull(toStringDefault(""));
    }

    /**
     * <p>Convert a <code>Object</code> to a <code>String</code>
     *
     * @return String
     * @throws NullPointerException – if the value is null.
     * @see #convert(Object)
     */
    @Nonnull
    public String toStringThrow(){
        return convert(super.object);
    }
}
